import { FC, ReactElement, useState, useCallback, useEffect } from "react";
import styled, { keyframes } from "styled-components";
import { useSocketContext } from "../../api/context/SocketContext";
import { EMIT, EVENT } from "../../api/types";
import { IOpponent } from "./types";
import verify from "../../api/TicTacToeHelper";

interface IProps {
  opponent: IOpponent;
}

const Grid: FC<IProps> = ({ opponent }): ReactElement => {
  const [checkerBoard, setCheckerBoard] = useState(Array.from({ length: 9 }));
  const [shouldGo, setShouldGo] = useState<string>();
  const [{ socket, nickname }] = useSocketContext();

  const changeCheckerBoard = useCallback((index, nickname) => {
    setCheckerBoard((prev) => {
      const arr = [...prev];
      arr.splice(index, 1, nickname);
      return arr;
    });
  }, []);

  const getWin = useCallback(() => {
    socket.emit(EMIT.WIN, opponent.socketId);
    setTimeout(() => {
      alert("you win 👍🏻");
    }, 0);
  }, [opponent.socketId, socket]);

  useEffect(() => {
    if (socket.on) {
      socket.on(EVENT.SHOULD_GO, (nickname: string) => {
        setShouldGo(nickname);
      });
      socket.on(EVENT.PLAYED_CHESS, (payload: any) => {
        const { index, nickname } = JSON.parse(payload);
        changeCheckerBoard(index, nickname);
      });
      socket.on(EVENT.WINED, () => {
        alert("对方获得胜利,哪里出了问题呢🤔");
      });
    }
  }, [changeCheckerBoard, socket]);

  const playChess = (index: number) => () => {
    //等待对方落子中
    if (shouldGo !== nickname) {
      console.log("请等对方落子");
      return;
    }
    if (checkerBoard[index]) {
      console.log("不能重复落子");
      return;
    }
    //告诉对方下在哪个位置
    const payload = { index, ...opponent };
    socket.emit(EMIT.PLAY_CHESS, JSON.stringify(payload));
    //本地变更
    changeCheckerBoard(index, nickname);
    const isWin = verify(index, checkerBoard, nickname);
    if (isWin) getWin();
  };

  return (
    <Container>
      {opponent.nickname ? (
        <WhoShouldGo shouldGo={shouldGo === nickname} />
      ) : null}
      <ChessContainer>
        {checkerBoard.map((gamer, index) => {
          return (
            <GridItem
              gamer={gamer}
              self={gamer === nickname}
              playChess={playChess(index)}
              key={index}
            />
          );
        })}
      </ChessContainer>
      {opponent.nickname ? (
        <Headline>
          {nickname} <Headline style={{ color: "red" }}>VS</Headline>{" "}
          {opponent.nickname}
        </Headline>
      ) : null}
    </Container>
  );
};

export default Grid;

const WhoShouldGo = ({ shouldGo }: { shouldGo: boolean }) => {
  return <Headline>{shouldGo ? "请落子" : "等待对方落子"}</Headline>;
};

const Container = styled.div`
  width: 75vw;
  height: calc(100vh - 4rem);
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
`;

const ChessContainer = styled.div`
  width: 75vmin;
  height: 75vmin;
  display: flex;
  flex-wrap: wrap;
  background: linear-gradient(145deg, #e1e1e1, #ffffff);
  box-shadow: 9px 9px 12px #b2b2b2, -9px -9px 12px #ffffff;
`;

const Headline = styled.strong`
  text-align: center;
  line-height: 3rem;
  flex: 1;
  user-select: none;
`;

const styles = `
  0% {
    border-color:#51f;
  }
  25%{
    border-color:#d35f07;
  }
  50% {
    border-color:#04f7ff;
  }
  75%{
    border-color:#d35f07;
  }
  100% {
    border-color: #51f;
  }
`;

const borderColorLinear = () => keyframes`${styles}`;

const Box = styled.div`
  border: 1px solid #51f;
  width: calc(100% / 3);
  height: calc(100% / 3);
  display: flex;
  justify-content: center;
  align-items: center;
  animation: ${borderColorLinear} 8s linear infinite alternate;
`;

const GridItem = ({
  playChess,
  gamer,
  self,
}: {
  playChess: () => void;
  gamer: string | unknown;
  self: boolean;
}) => {
  return (
    <Box onClick={playChess}>
      {/* 没有gamer 还没下呢 不显示 */}
      {!gamer ? <></> : self ? <RightIcon /> : <ErrorIcon />}
    </Box>
  );
};

const RightIcon = () => (
  <svg
    viewBox="0 0 1024 1024"
    version="1.1"
    xmlns="http://www.w3.org/2000/svg"
    p-id="2415"
    width="128"
    height="128"
  >
    <path
      d="M610 672.09a18.48 18.48 0 0 1-13.06-31.54L902.44 335a43.16 43.16 0 0 0 0-60.93L834 205.44a43.25 43.25 0 0 0-60.7-0.35l-299.83 293.8a18.48 18.48 0 1 1-25.86-26.39l299.86-293.8a80.27 80.27 0 0 1 112.74 0.66L928.66 248a80.16 80.16 0 0 1-0.1 113.14L623.05 666.67a18.42 18.42 0 0 1-13.05 5.42z"
      fill="#0897EA"
      p-id="2416"
    ></path>
    <path
      d="M414 868.09a18.52 18.52 0 0 1-7.87-1.76 17.24 17.24 0 0 1-6.84-4.2L77.44 540.3a18.47 18.47 0 0 1 0-26.12L235 356.39a18.47 18.47 0 0 1 26-0.13l165.37 162.4c0.1 0.08 0.18 0.18 0.26 0.26L584 679.94a18.47 18.47 0 0 1-0.18 25.95L427 862.68a18.42 18.42 0 0 1-13 5.41zM116.62 527.23L413.43 824l131.38-131.34L400.35 544.9 248.19 395.46z"
      fill="#FF4056"
      p-id="2417"
    ></path>
  </svg>
);

const ErrorIcon = () => (
  <svg
    viewBox="0 0 1024 1024"
    version="1.1"
    xmlns="http://www.w3.org/2000/svg"
    p-id="2363"
    width="128"
    height="128"
  >
    <path
      d="M1.264376 1.257151h1021.478473v1021.492923H1.264376z"
      fill="#769AFF"
      p-id="2364"
    ></path>
    <path
      d="M1.264376 1.257151l1021.471248 1021.485698M1.264376 1022.742849L1022.735624 1.257151"
      fill="#769AFF"
      p-id="2365"
    ></path>
    <path
      d="M615.837776 508.539222l224.87829-224.871064c28.213646-28.213646 28.213646-73.962379 0-102.18325-28.220871-28.206421-73.955154-28.206421-102.18325 0L513.654526 406.363198 288.790687 181.484908c-28.220871-28.206421-73.955154-28.206421-102.18325 0-28.213646 28.213646-28.213646 73.962379 0 102.18325l224.871064 224.871064-224.871064 224.87829c-28.213646 28.213646-28.213646 73.962379 0 102.176025a72.047753 72.047753 0 0 0 51.088012 21.162041 72.033303 72.033303 0 0 0 51.088013-21.162041l224.871064-224.87829 224.87829 224.87829a72.047753 72.047753 0 0 0 51.088012 21.162041 72.033303 72.033303 0 0 0 51.088013-21.162041c28.213646-28.213646 28.213646-73.962379 0-102.176025L615.837776 508.539222z"
      fill="#FFFFFF"
      p-id="2366"
    ></path>
  </svg>
);
